home *** CD-ROM | disk | FTP | other *** search
/ ASME's Mechanical Engine…ing Toolkit 1997 December / ASME's Mechanical Engineering Toolkit 1997 December.iso / c_lang / super_c.lzh / SQUIG.C < prev    next >
Text File  |  1980-01-01  |  11KB  |  274 lines

  1. /*                      Fractal Generation Program
  2. */
  3.  
  4. #include <stdio.h>
  5. #include <math.h>
  6.  
  7. #define FALSE 0
  8. #define TRUE 1
  9.  
  10. /* Movement directions: */
  11.  
  12. #define UP 0
  13. #define DOWN 1
  14. #define LEFT 2
  15. #define RIGHT 3
  16.  
  17. /* Table to convert from the direction of a segment being drawn (first
  18.    index) and the direction of a subsegment (second index) to absolute
  19.    screen up/down/left/right: */
  20.  
  21. int dirDir[4][4] = {
  22.         LEFT, RIGHT, DOWN, UP,  /* Line up. */
  23.         RIGHT, LEFT, UP, DOWN,  /* Line down. */
  24.         DOWN, UP, RIGHT, LEFT,  /* Line left. */
  25.         UP, DOWN, LEFT, RIGHT   /* Line right. */
  26. };
  27.  
  28. /* X-axis multiplier for up/down/left/right movement: */
  29.  
  30. int xDir[4] = {
  31.         0, 0, -1, 1     /* Line right. */
  32. };
  33.  
  34. /* Y-axis multiplier for up/down/left/right movement: */
  35.  
  36. int yDir[4] = {
  37.         -1, 1, 0, 0     /* Line right. */
  38. };
  39.  
  40. int boxPatt[100];       /* The box pattern. */
  41. int boxPSz;             /* It's size. */
  42.  
  43. int linePatt[100];      /* The line pattern. */
  44. int linePSz;            /* It's size. */
  45. int lineLen;            /* Width of line pattern in line segments. */
  46.  
  47. int level;              /* The level of detail to go to. */
  48.  
  49. float x, y;             /* The current pen position. */
  50.  
  51. int color;              /* The current pen color. */
  52.  
  53. /*      main()
  54.  
  55.         Function: Get box and line patterns, the line size, and the
  56.         level to draw to from the user. Then draw the fractal. When
  57.         done, ask if another one should be drawn. Repeat the sequence
  58.         as long as the user wants.
  59.  
  60.         Algorithm: Use getPatt to read in the patterns for the box and
  61.         the line pattern. Use gets/atoi for the other, numeric input.
  62.         Then call doPatt to actually draw the fractal.
  63. */
  64.  
  65. main()
  66.  
  67. {
  68.         char str[100];  /* Input buffer for user responses. */
  69.         int side;       /* Size of line in screen dots. */
  70.  
  71.         /* Repeat while the user wants more. */
  72.         do {
  73.                 /* Set the display mode; use 6 for CGA, 14 for EGA with
  74.                    color display, or 16 for EGA with enhanced color disp. */
  75.                 setMod(6);
  76.                 /* Get the box pattern. */
  77.                 getPatt("box",boxPatt,&boxPSz,TRUE,TRUE);
  78.                 /* Get the size of the box line. */
  79.                 printf("Side size: ");
  80.                 gets(str);
  81.                 side = atoi(str);
  82.                 /* Get the line pattern. */
  83.                 lineLen = getPatt("line",linePatt,&linePSz,TRUE,FALSE);
  84.                 /* Get the level to display to. */
  85.                 printf("Level: ");
  86.                 gets(str);
  87.                 level = atoi(str);
  88.                 /* Set the pen position and color to start with. */
  89.                 x = 270; y = 50; color = 7;
  90.                 /* Draw the fractal. */
  91.                 doPatt(boxPatt,boxPSz,RIGHT,(float) side,0);
  92.                 /* Ask if the user wants to do another one. */
  93.                 printf("Do another one? ");
  94.                 gets(str);
  95.         } while ((str[0] == 'y') || (str[0] == 'Y'));
  96. }
  97.  
  98. /*      getPatt(prmpt,patt,size,noUp,noLeft)
  99.  
  100.         Function: Get a pattern from the user. Issue the prompt
  101.         string pointed to by prmpt. Then read the pattern into
  102.         the pattern array pointed to by patt, and set the size
  103.         pointed to by size. If noUp is TRUE, don't allow patterns
  104.         that end at a different up/down level than they began.
  105.         If noLeft is TRUE, don't allow patterns that end at a
  106.         different left/right level than they started. getPatt
  107.         returns the number of segments to the right the pattern
  108.         ends at from its starting position.
  109.  
  110.         Algorithm: Prompt the user and then read in the pattern
  111.         string. Scan through it, converting from 'u'/'d'/'l'/'r'
  112.         to UP/DOWN/LEFT/RIGHT. When done, check it for validity.
  113.         If it fails, tell the user and do it all over again.
  114. */
  115.  
  116. getPatt(prmpt,patt,size,noUp,noLeft)
  117.  
  118. char *prmpt;
  119. int *patt;
  120. int *size;
  121. int noUp;
  122. int noLeft;
  123.  
  124. {
  125.         char str[100];          /* Input buffer for user input. */
  126.         char *cp;               /* Char pointer to scan buffer with. */
  127.         int *pPtr;              /* Pattern array pointer. */
  128.         int upCnt, rightCnt;    /* Up/down and left/right offsets. */
  129.         int badPatt;            /* TRUE if pattern is bad. */
  130.  
  131.         /* Repeat until he gets it right. */
  132.         do {
  133.                 /* Prompt him for a pattern string. */
  134.                 printf("Enter %s pattern: ",prmpt); gets(str);
  135.                 /* Assume the pattern's OK. */
  136.                 badPatt = FALSE;
  137.                 /* Scan through the pattern string. */
  138.                 for (cp = str, pPtr = patt, upCnt = rightCnt = 0, *size = 0;
  139.                      *cp != 0; cp++, pPtr++, (*size)++) {
  140.                         switch (*cp) {
  141.                                 case 'u':
  142.                                 case 'U':
  143.                                         /* Up one. */
  144.                                         *pPtr = UP;
  145.                                         upCnt++;
  146.                                         break;
  147.                                 case 'd':
  148.                                 case 'D':
  149.                                         /* Down one. */
  150.                                         *pPtr = DOWN;
  151.                                         upCnt--;
  152.                                         break;
  153.                                 case 'l':
  154.                                 case 'L':
  155.                                         /* Left one. */
  156.                                         *pPtr = LEFT;
  157.                                         rightCnt--;
  158.                                         break;
  159.                                 case 'r':
  160.                                 case 'R':
  161.                                         *pPtr = RIGHT;
  162.                                         rightCnt++;
  163.                                         break;
  164.                                 default:
  165.                                         badPatt = TRUE;
  166.                                         break;
  167.                         };
  168.                         if (badPatt) {
  169.                                 printf("Only U, D, L, or R allowed!\n");
  170.                                 break;
  171.                         };
  172.                 };
  173.                 if (noUp && (upCnt != 0)) {
  174.                         printf("Pattern must end at the same up/down level ");
  175.                         printf("it began at.\n");
  176.                         badPatt = TRUE;
  177.                 };
  178.                 if (noLeft && (rightCnt != 0)) {
  179.                         printf("Pattern must end at the same right/left ");
  180.                         printf("level it began at.\n");
  181.                         badPatt = TRUE;
  182.                 };
  183.         } while (badPatt);
  184.         return(rightCnt);
  185. }
  186.  
  187. /*      doPatt(patt,pattSize,dir,size,lev)
  188.  
  189.         Function: Draw the pattern pointed to by patt, of size pattSize,
  190.         in the direction dir (UP, DOWN, LEFT, or RIGHT), with each line
  191.         segment of size size; this will be level lev. If lev doesn't yet
  192.         match the global variable level, then recursively call doPatt to
  193.         draw each segment as a series of segments from the line pattern.
  194.  
  195.         Algorithm: For each segment in the pattern, if we're at the drawing
  196.         level (lev == level), then figure out the proper direction to
  197.         draw and draw the segment; otherwise, call doPatt to draw the
  198.         sub-pattern.
  199. */
  200.  
  201. doPatt(patt,pattSize,dir,size,lev)
  202.  
  203. int *patt;
  204. int pattSize;
  205. int dir;
  206. float size;
  207. int lev;
  208.  
  209. {
  210.         int *pPtr;                      /* A pointer into the pattern. */
  211.         int pCnt;                       /* Count of pattern segments left. */
  212.         int xPlusMinus, yPlusMinus;     /* The x and y drawing increments. */
  213.         register int i, j;              /* Row and column drawing indices. */
  214.         int iEnd, jEnd;                 /* Where to stop drawing. */
  215.         int temp;
  216.         int subDir;                     /* The absolute up/down/left/right. */
  217.         int dotVal;                     /* Color to draw. */
  218.  
  219.         /* For each segment in the pattern... */
  220.         for (pPtr = patt, pCnt = 0; pCnt++ < pattSize; pPtr++) {
  221.                 /* If we're at drawing level... */
  222.                 if (lev == level) {
  223.                         /* Find the absolute direction. */
  224.                         subDir = dirDir[dir][*pPtr];
  225.                         /* Convert the pen position to row/column ints. */
  226.                         i = x; j = y;
  227.                         /* Get the pen increment for drawing. */
  228.                         xPlusMinus = xDir[subDir]; 
  229.                         yPlusMinus = yDir[subDir];
  230.                         /* Compute the new pen position after drawing. */
  231.                         x += xPlusMinus*size; y += yPlusMinus*size;
  232.                         /* Convert the end point to row/column ints. */
  233.                         iEnd = x; jEnd = y;
  234.                         /* We always want to draw in ascending coordinates.
  235.                            Therefore, we must swap i/iEnd and j/jEnd if
  236.                            we'd be drawing descending. */
  237.                         if (iEnd < i) {
  238.                                 temp = i; i = iEnd; iEnd = temp;
  239.                         };
  240.                         if (jEnd < j) {
  241.                                 temp = j; j = jEnd; jEnd = temp;
  242.                         };
  243.                         /* Similarly, we need the abs of the increments. */
  244.                         xPlusMinus = abs(xPlusMinus); 
  245.                         yPlusMinus = abs(yPlusMinus);
  246.                         /* Set the color to draw. For the EGA, this should
  247.                            be the global variable color; for CGA, it should
  248.                            be 1. */
  249.                         dotVal = 1 /*color*/;
  250.                         /* Decide whether we're drawing a vertical or
  251.                            horizontal line. */
  252.                         if (xPlusMinus == 0) {
  253.                                 /* If vertical, draw it. */
  254.                                 do putDot(0,j++,i,dotVal); while (j < jEnd);
  255.                         } else {
  256.                                 /* If horizontal, draw it. */
  257.                                 do putDot(0,j,i++,dotVal); while (i < iEnd);
  258.                         };
  259.  
  260.                 /* If we're not down to drawing level yet, call doPatt to
  261.                    draw the next level down. */
  262.                 } else doPatt(linePatt,linePSz,dirDir[dir][*pPtr],
  263.                               size/((float) lineLen),lev+1);
  264.  
  265.                 /* If this is the top level, switch to the next color for 
  266.                    drawing the next segment. */
  267.                 if (lev == 0) {
  268.                         color--;
  269.                         if (color == 0) color = 15;
  270.                 };
  271.         };
  272. }
  273.  
  274.